/*
=======================================================================

  Scientist - BOTS
  
=======================================================================
*/
#include "g_local.h"

#include "bots_game2cgame.h"

#include "bg_local.h"
#include "bots_local.h"
#include "bots_Scientist.h"

#define	AMMO_COST		50
#define	QUAD_COST		200
#define	HASTE_COST		100
#define BATTLE_COST		150

void BOTS_tech(int clientNum, qboolean ab_techall);

void bots_updateClientData_scientist(gentity_t *self, bots_g2cg_scientist_t *p) {
	if (!self->client)
		return;

	// Proxies? grenade/weapon modes?
	p->weapons.gren1 = p->weapons.gren2	= p->weapons.weaponmode = 0;
	p->weapons.grenademode	= self->client->qb_teleportMode;
}

// Ad hoc function as that state is not preserved anywhere. Argh.
static void bots_updateKeyDistanceScientist(gentity_t *self, short sKeyDistance) {
	BOTS_G2CG_GETCLASSDATA(bots_g2cg_captain_t,self)->sKeyDistance = sKeyDistance;
}


void BOTS_techkey_think(gentity_t* self)
{
	G_AddEvent( self, ET_BOTS_HEAL, self->s.modelindex );
	self->nextthink = level.time + FRAMETIME;
}


void BOTS_droptech(int clientNum, qboolean launch)
{
	gentity_t*  ent = g_entities + clientNum;
	gentity_t*	drop;
	gitem_t*	item;
	vec3_t		angles, velocity, origin, forward, right, up, muzzle, wallp;
	trace_t		tr1;
	int			i;

	if (ent->bots_class != BOTS_SCIENTIST)
	{
		BOTS_cp_console(clientNum, "Only Scientists have tech keys.");
		return;	
	}

	if (ent->techkey)
	{
		BOTS_cp_console(clientNum, "You don't have the tech key.");
		return;	
	}

	bots_setScientistLostKey(ent->bots_team, qtrue);

	// set aiming directions
	AngleVectors (ent->client->ps.viewangles, forward, NULL, NULL);

	// setup muzzle point
	CalcMuzzlePoint(ent, forward, NULL, NULL, muzzle);

	if (launch)
	{
		// Setup end point of the vector we want to trace
		VectorCopy(muzzle, wallp);
		VectorMA(wallp, 50, forward, wallp);
		trap_Trace(&tr1, muzzle, NULL, NULL, wallp, ent->s.number, MASK_SOLID);
		SnapVector( tr1.endpos );

		// check to make sure we are not too close to a wall	
		if (tr1.fraction != 1)
			return;
	}

	if (ent->client->sess.sessionTeam == TEAM_RED)
		item = BG_FindItem("Red Tech Key");
	else
		item = BG_FindItem("Blue Tech Key");

	// set aiming directions
	VectorCopy( ent->s.apos.trBase, angles );

	forward[2] = 0;
	VectorCopy(ent->s.pos.trBase, origin);

	angles[PITCH] = 0;	// always forward

	if (launch)
	{
		AngleVectors( angles, velocity, NULL, NULL );
		VectorScale( velocity, 150, velocity );
		velocity[2] += 100;
	}
	else
		VectorSet(velocity, 0, 0, 0);

	drop = LaunchItem( item, origin, velocity );
	drop->parent = ent;
	drop->i_dropTime = level.time;

	// tilt the head to look up a bit
	AngleVectors (ent->client->ps.viewangles, NULL, right, up);
	right[2] = 0;
	VectorScale(forward, -1, forward);
	BOTS_vectorFromAngle(forward, axisDefault[2], right, 60, forward);
	vectoangles(forward, drop->s.apos.trBase);

	// set all team mates techkey entity to this key
	for (i = 0; i < level.maxclients; i++)
	{
		gentity_t* player = &g_entities[i];

		if (!ent->client)
			continue;
		if (player->client->sess.sessionTeam == TEAM_SPECTATOR)
			continue;
		if (!OnSameTeam (ent, player))
			continue;

		player->techkey = drop;
	}
}

	
void BOTS_scientistCreate_setup(int clientNum)
{
	gentity_t*	ent = g_entities + clientNum;
	char*		create_string;
	int			li_modifier;

	if (!ent->client)
		return;

	li_modifier = ent->client->pers.classlevel;

	// check level
	if (li_modifier < 1)
	{
		BOTS_cp_console( clientNum, "You must be at least level 1 to create.");
		return;
}

	// check ammo
	if (ent->client->ps.ammo[WP_BFG] < AMMO_COST / li_modifier)
	{
		BOTS_cp_console( clientNum, va("You need at least %i cells to create.", (int)AMMO_COST / li_modifier));
		return;
	}

	create_string = va("\\a\\1");


	// haste
	if (ent->client->ps.ammo[WP_BFG] >= HASTE_COST)
		create_string = va("%s\\h\\1", create_string);
	else
		create_string = va("%s\\h\\2", create_string);

	// battle suit
	if (ent->client->ps.ammo[WP_BFG] >= BATTLE_COST)
		create_string = va("%s\\b\\1", create_string);
	else
		create_string = va("%s\\b\\2", create_string);

	// megahealth
	if (ent->client->ps.ammo[WP_BFG] >= QUAD_COST)
		create_string = va("%s\\q\\1", create_string);
	else
		create_string = va("%s\\q\\2", create_string);
	
	// set the menu list
	trap_SetConfigstring(CS_BOTS_MENU + clientNum, create_string);

	// tell cgame we are done so it can send to the UI.
	trap_SendServerCommand(clientNum, "create_data_complete");
}


void BOTS_scientistCreate_item(int clientNum, char* item_string)
{
	gentity_t*	ent = g_entities + clientNum;
	gentity_t*	drop;
	gitem_t*	item;
	vec3_t		angles, velocity, origin, forward;
	int			li_modifier;

	if (!ent->client)
		return;
	
	li_modifier = ent->client->pers.classlevel;
	if (li_modifier < 1)
		li_modifier = 1;

	if (Q_stricmp (item_string, "bullets") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) AMMO_COST / li_modifier;
		item = BG_FindItem("Bullets");
	}
	else if (Q_stricmp (item_string, "shells") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) AMMO_COST / li_modifier;
		item = BG_FindItem("Shells");
	}
	else if (Q_stricmp (item_string, "slugs") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) AMMO_COST / li_modifier;
		item = BG_FindItem("Slugs");
	}
	else if (Q_stricmp (item_string, "grenades") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) AMMO_COST / li_modifier;
		item = BG_FindItem("Grenades");
	}
	else if (Q_stricmp (item_string, "rockets") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) AMMO_COST / li_modifier;
		item = BG_FindItem("Rockets");
	}
//	else if (Q_stricmp (item_string, "cells") == 0 )
//	{
//		ent->client->ps.ammo[WP_BFG] -= (int) AMMO_COST / li_modifier;
//		item = BG_FindItem("Cells");
//	}
	else if (Q_stricmp (item_string, "quaddamage") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) QUAD_COST;
		item = BG_FindItem("Quad Damage");
	}
	else if (Q_stricmp (item_string, "haste") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) HASTE_COST;
		item = BG_FindItem("Speed");
	}
	else if (Q_stricmp (item_string, "battlesuit") == 0 )
	{
		ent->client->ps.ammo[WP_BFG] -= (int) BATTLE_COST;
		item = BG_FindItem("Battle Suit");
	}
	else
	{
		BOTS_cp_console( clientNum, "BAD ITEM FROM MENU.");
		return;
	}

	// taken from Drop_Item

	// set aiming directions
	VectorCopy( ent->s.apos.trBase, angles );

	// set the origin of the launch away from the client
	AngleVectors (ent->client->ps.viewangles, forward, NULL, NULL);
	forward[2] = 0;
	VectorMA(ent->s.pos.trBase, 100, forward, origin);

	angles[PITCH] = 0;	// always forward

	AngleVectors( angles, velocity, NULL, NULL );
	VectorScale( velocity, 150, velocity );
	velocity[2] += 200 + crandom() * 50;

	drop = LaunchItem( item, origin, velocity );

	if (Q_stricmp (item_string, "quaddamage") == 0 ||
		Q_stricmp (item_string, "haste") == 0 ||
		Q_stricmp (item_string, "battlesuit") == 0)
		drop->count = 15;
}

/////////////////////////////////////////////
//
// BOTS_ScientistCommands
//
// This will parse the passed cmd string and call to the correct functions.
// 
// RETURNS
//    qfalse : cmd is not an Scientist command
//	  qtrue	 : cmd is a Scientist command
//
qboolean BOTS_ScientistCommands(int clientNum, char* cmd)
{
	if (Q_stricmp (cmd, "droptech") == 0 )
	{
		BOTS_droptech(clientNum, qtrue);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "tech") == 0 )
	{
		BOTS_tech(clientNum, qfalse);
		return qtrue;
	}
	else if (Q_stricmp (cmd, "techall") == 0 )
	{
		BOTS_tech(clientNum, qtrue);
		return qtrue;
	}
//	else if (Q_stricmp (cmd, "createbot") == 0 )
//	{
//		BOTS_createbot(clientNum, qtrue);
//		return qtrue;
//	}
//	else if (Q_stricmp (cmd, "killbot") == 0 )
//	{
//		BOTS_killbot(clientNum, qtrue);
//		return qtrue;
//	}

	return qfalse;
}


gentity_t *SelectRandomTeamSpawnPoint( int teamstate, team_t team, int ai_class );

void BOTS_teleport_explode( gentity_t* self) 
{
	gentity_t*	player = NULL;
	gentity_t*	dest = NULL;
	int			range = 200;

	if (!self->parent)
		return;
	if (!self->parent->client)
		return;

	if (self->parent->client->pers.classlevel == 1)
		range = 100;
	else if (self->parent->client->pers.classlevel > 2)
		range += 200 * self->parent->client->pers.classlevel;

	while ((player = findradiusCLIENT(player, self->s.pos.trBase, 200)) != NULL)
	{
		if (!player->client)
			continue;
		if (player->health <= 0)
			continue;
		if (OnSameTeam(player, self->parent))
			continue;
		if (!visible(player, self))
			continue;

		// Teleport the player
		dest = SelectRandomTeamSpawnPoint ( TEAM_ACTIVE, player->bots_team, player->bots_class );
		if (!dest)
		{
			// G_Printf ("Couldn't find teleporter destination\n");
		}
		else
			TeleportPlayer( player, dest->s.origin, dest->s.angles );
	}


	self->think = G_ExplodeMissile;
	self->nextthink = level.time + FRAMETIME;
	trap_LinkEntity( self );
}


/////////////////////////////////////////////
//
// BOTS_ClientThink_scientist
//
// Scientist think routine.  Called once for each client think if
// the client is a Scientist.
//
void BOTS_ClientThink_scientist(gentity_t* ent)
{
	// tech key distance
	if (ent->techkey)
	{
		vec3_t	dist1;
		int		len;
		float	lf_lostkey;

		VectorSubtract(ent->s.pos.trBase, ent->techkey->s.pos.trBase, dist1);
		len = VectorLength(dist1);
		bots_updateKeyDistanceScientist(ent,(short)len);

		lf_lostkey = bots_getScientistLostKey(ent->bots_team);
		if ((lf_lostkey) && ((lf_lostkey + 60000) < level.time)) {
			bots_setScientistLostKey(ent->bots_team, qtrue);
			BOTS_touch_tech_key(ent->techkey, ent);
			BOTS_cp_console(ent->s.clientNum, "Your Tech Key has been returned!");
		}
	}
	else
		bots_updateKeyDistanceScientist(ent,0);

	if (ent->health <= 0)
		return;
}
